package cn.grab.fispservice.upms.service.impl;

import cn.grab.fispapi.upms.dto.SysAddRoleDTO;
import cn.grab.fispapi.upms.vo.SysRoleVO;
import cn.grab.fispservice.upms.model.SysRole;
import cn.grab.fispservice.upms.model.SysRole.SysRoleModelMapper;
import cn.grab.fispservice.upms.model.SysRoleMenu;
import cn.grab.fispservice.upms.model.SysUserRole;
import cn.grab.fispservice.upms.mapper.SysRoleMapper;
import cn.grab.fispservice.upms.mapper.SysRoleMenuMapper;
import cn.grab.fispservice.upms.mapper.SysUserRoleMapper;
import cn.grab.fispservice.upms.service.SysMenuService;
import cn.grab.fispservice.upms.service.SysRoleService;
import cn.grab.fispservice.upms.service.SysUserService;
import cn.grab.fispservice.util.ThreadLocalUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fontana.base.result.CallResult;
import com.fontana.base.result.Result;
import com.fontana.base.result.ResultCode;
import com.fontana.db.mapper.BaseDaoMapper;
import com.fontana.db.mapper.BaseModelMapper;
import com.fontana.db.model.BaseLogicDelModel;
import com.fontana.db.service.impl.AbstractBaseService;
import com.fontana.util.bean.BeanUtil;
import com.fontana.util.tools.IdUtil;
import java.util.ArrayList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 角色数据服务类。
 *
 * @author cqf
 * @date 2020-08-08
 */
@Slf4j
@Service("sysRoleService")
public class SysRoleServiceImpl extends AbstractBaseService<SysRole, Long> implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysUserService sysUserService;



    /**
     * 返回主对象的Mapper对象。
     *
     * @return 主对象的Mapper对象。
     */
    @Override
    protected BaseDaoMapper<SysRole> mapper() {
        return sysRoleMapper;
    }

    /**
     * 保存新增的角色对象。
     *
     * @param role      新增的角色对象。
     * @param menuIdSet 菜单Id列表。
     * @return 新增后的角色对象。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysRole saveNew(SysRole role, Set<Long> menuIdSet) {
        role.setRoleId(IdUtil.nextLongId());
//        role.setDeletedFlag(GlobalDeletedFlag.NORMAL);
//        MyModelUtil.fillCommonsForInsert(role);
        sysRoleMapper.insert(role);
        if (menuIdSet != null) {
            for (Long menuId : menuIdSet) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(role.getRoleId());
                roleMenu.setMenuId(menuId);
                sysRoleMenuMapper.insert(roleMenu);
            }
        }
        return role;
    }

    /**
     * 更新角色对象。
     *
     * @param role         更新的角色对象。
     * @param originalRole 原有的角色对象。
     * @param menuIdSet    菜单Id列表。
     * @return 更新成功返回true，否则false。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean update(SysRole role, SysRole originalRole, Set<Long> menuIdSet) {
        //MyModelUtil.fillCommonsForUpdate(role, originalRole);
        if (sysRoleMapper.updateById(role) != 1) {
            return false;
        }
        SysRoleMenu deletedRoleMenu = new SysRoleMenu();
        deletedRoleMenu.setRoleId(role.getRoleId());
        sysRoleMenuMapper.delete(new QueryWrapper<>(deletedRoleMenu));
        if (menuIdSet != null) {
            for (Long menuId : menuIdSet) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(role.getRoleId());
                roleMenu.setMenuId(menuId);
                sysRoleMenuMapper.insert(roleMenu);
            }
        }
        return true;
    }

    /**
     * 删除指定角色。
     *
     * @param roleId 角色主键Id。
     * @return 删除成功返回true，否则false。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean remove(Long roleId) {
        if (sysRoleMapper.deleteById(roleId) != 1) {
            return false;
        }
        SysRoleMenu roleMenu = new SysRoleMenu();
        roleMenu.setRoleId(roleId);
        sysRoleMenuMapper.delete(new QueryWrapper<>(roleMenu));
        SysUserRole userRole = new SysUserRole();
        userRole.setRoleId(roleId);
        sysUserRoleMapper.delete(new QueryWrapper<>(userRole));
        return true;
    }

    @Override
    public List<SysUserRole> getSysUserRoleListByUserId(Long userId) {
        SysUserRole filter = new SysUserRole();
        filter.setUserId(userId);
        return sysUserRoleMapper.selectList(new QueryWrapper<>(filter));
    }

    /**
     * 获取角色列表。
     *
     * @param filter  角色过滤对象。
     * @param orderBy 排序参数。
     * @return 角色列表。
     */
    @Override
    public List<SysRole> getSysRoleList(SysRole filter, String orderBy) {
        return sysRoleMapper.getSysRoleList(filter, orderBy);
    }

    /**
     * 批量新增用户角色关联。
     *
     * @param userRoleList 用户角色关系数据列表。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addUserRoleList(List<SysUserRole> userRoleList) {
        for (SysUserRole userRole : userRoleList) {
            sysUserRoleMapper.insert(userRole);
        }
    }

    /**
     * 移除指定用户和指定角色的关联关系。
     *
     * @param roleId 角色主键Id。
     * @param userId 用户主键Id。
     * @return 移除成功返回true，否则false。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeUserRole(Long roleId, Long userId) {
        SysUserRole userRole  = new SysUserRole();
        userRole.setRoleId(roleId);
        userRole.setUserId(userId);
        return sysUserRoleMapper.delete(new QueryWrapper<>(userRole)) == 1;
    }

    /**
     * 验证角色对象关联的数据是否都合法。
     *
     * @param sysRole          当前操作的对象。
     * @param originalSysRole  原有对象。
     * @param menuIdListString 逗号分隔的menuId列表。
     * @return 验证结果。
     */
    @Override
    public CallResult verifyRelatedData(SysRole sysRole, SysRole originalSysRole, String menuIdListString) {
        JSONObject jsonObject = null;
        if (StringUtils.isNotBlank(menuIdListString)) {
            Set<Long> menuIdSet = Arrays.stream(
                    menuIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet());
            if (!sysMenuService.existAllPrimaryKeys(menuIdSet)) {
                return CallResult.error("数据验证失败，存在不合法的菜单权限，请刷新后重试！");
            }
            jsonObject = new JSONObject();
            jsonObject.put("menuIdSet", menuIdSet);
        }
        return CallResult.ok(jsonObject);
    }

    /**
     * 查询角色的权限资源地址列表。同时返回详细的分配路径。
     *
     * @param roleId 角色Id。
     * @param url    url过滤条件。
     * @return 包含从角色到权限资源的完整权限分配路径信息的查询结果列表。
     */
    @Override
    public List<Map<String, Object>> getSysPermListWithDetail(Long roleId, String url) {
        return sysRoleMapper.getSysPermListWithDetail(roleId, url);
    }

    /**
     * 查询角色的权限字列表。同时返回详细的分配路径。
     *
     * @param roleId   角色Id。
     * @param permCode 权限字名称过滤条件。
     * @return 包含从角色到权限字的权限分配路径信息的查询结果列表。
     */
    @Override
    public List<Map<String, Object>> getSysPermCodeListWithDetail(Long roleId, String permCode) {
        return sysRoleMapper.getSysPermCodeListWithDetail(roleId, permCode);
    }

    /**
     校验当前选择角色是否冲突

     @param  accountRole   角色Id集合。
     @return 角色是否冲突 是 true  否 false
     */
    @Override
    public boolean findAccountRole(List<Long> accountRole) {

        //根据当前用户集合查询角色数据
        List<SysRole> sysRoles = sysRoleMapper.selectBatchIds(accountRole);

        List<String> roleNames = sysRoles.stream().map(SysRole::getRoleName)
            .collect(Collectors.toList());

        //设置冲突的角色类型
        List<String> conflictingRoles = new ArrayList<>();
        conflictingRoles.add("专家");
        conflictingRoles.add("供应商");

        //比较两个集合是否相同,返回结果
        return CollectionUtils.isEqualCollection(conflictingRoles, roleNames);
    }

    /**
     *@Param:
     *@return:  返回当前用户选择的角色
     *@Author: xxxx
     *@date: 2022/12/22
     */
    @Override
    public List<SysRoleVO> getSysRoleVOList() {
        //获取当前登录用户信息
        Long userId = ThreadLocalUtils.get();


        //根据userId查询当前的用户绑定的角色信息
        //创建lambdaquerywar
        LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<SysUserRole>().eq(
            SysUserRole::getUserId, userId);
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(queryWrapper);

        //获取当前选择的角色id
         List<Long> sysRoleIds = sysUserRoles.stream().map(SysUserRole::getRoleId)
            .collect(Collectors.toList());

         //根据角色id查询当前
        List<SysRole> sysRoles = sysRoleMapper.selectBatchIds(sysRoleIds);

        //调用将sysRoles转换成sysRoleVo,返回list
        return getSysRoleVO(sysRoles);
    }

    /**
     *@Param:
     *@return:  返回当前用户可选择的角色列表
     *@Author: xxxx
     *@date: 2022/12/22
     */
    @Override
    public List<SysRoleVO> getObtainRoleList() {

        //查询数据库表中所有的角色
        List<SysRole> sysRoles = sysRoleMapper.selectList(new QueryWrapper<>());

        //过滤掉平台管理员角色
        List<SysRole> roles = sysRoles.stream()
            .filter(sysRole -> sysRole.getRoleName().equals("平台管理员")).collect(Collectors.toList());

        //创建list集合,存储SysRoleVO对象
        List<SysRoleVO> sysRoleVOS = new ArrayList<>();

        //遍历集合,将SysRole对象转换成SysRoleVO
        for (SysRole role : roles) {
            //拷贝对象
            SysRoleVO sysRoleVO = BeanUtil.copy(role, SysRoleVO.class);
            sysRoleVOS.add(sysRoleVO);
        }
        return sysRoleVOS;
    }


    /**
      添加用户角色方法
     *@Param:
     *@return:  返回当前用户可选择的角色列表
     *@Author: xxxx
     *@date: 2022/12/22
     */
    @Override
    public Result<Object> addSysUserRole(SysAddRoleDTO sysAddRoleDTO) {
        //调用UserService修改默认角色游客为选中的角色
        sysUserService.updateDefaultRole(sysAddRoleDTO.getDefaultRole());


        //校验账号角色集合是否冲突
        //根据id查询数据库角色表中的信息
        boolean accountRoleResult = findAccountRole(sysAddRoleDTO.getAccountRole());

        if (accountRoleResult){
            return Result.failed(ResultCode.SYSTEM_INNER_ERROR, "角色选择出现冲突! 请重新选择");
        }

        //创建用户关联角色实体对象
        List<SysUserRole> userRoleList = new ArrayList<>();

        List<Long> accountRole = sysAddRoleDTO.getAccountRole();

        //获取当前登录的用户id
        Long userId = ThreadLocalUtils.get();


        for (Long RoleId : accountRole) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(RoleId);

            userRoleList.add(sysUserRole);
        }

        //查询当前用户是否已经选择过角色
        LambdaQueryWrapper<SysUserRole> eq = new LambdaQueryWrapper<SysUserRole>().eq(
            SysUserRole::getUserId, userId);
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(eq);


        if (sysUserRoles != null){
            //当前用户信息为null,修改用户选择的角色信息
            //直接根据用户id,删除选择的角色信息
            sysUserRoleMapper.delete(eq);
        }

        //当前用户角色信息为null,存储用户选择的角色信息进数据库
        addUserRoleList(userRoleList);

        return Result.failed(ResultCode.SUCCESS,"选择角色成功");
    }

    /**
     *@Param: sysRoles 需要转换的角色对象集合
     *@return:  返回转换后的对象集合
     *@Author: xxxx
     *@date: 2022/12/22
     */
    public List<SysRoleVO> getSysRoleVO(List<SysRole> sysRoles) {
        //创建list集合,存储SysRoleVO对象
        List<SysRoleVO> sysRoleVOS = new ArrayList<>();

        //遍历集合,将SysRole对象转换成SysRoleVO
        for (SysRole role : sysRoles) {
            //拷贝对象
            SysRoleVO sysRoleVO = BeanUtil.copy(role, SysRoleVO.class);
            sysRoleVOS.add(sysRoleVO);
        }

        return sysRoleVOS;
    }
}
